package travelDream.bean;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import travelDream.dto.DataDTO;
import travelDream.dto.EscursioneDTO;
import travelDream.dto.HotelDTO;
import travelDream.dto.PacchettoPreconfiguratoDTO;
import travelDream.dto.RisultatoRicercaPPDTO;
import travelDream.dto.VoloDTO;
import travelDream.entities.DataPossibilePP;
import travelDream.entities.Escursione;
import travelDream.entities.Hotel;
import travelDream.entities.IAttivita;
import travelDream.entities.PacchettoPreconfigurato;
import travelDream.entities.Volo;
import travelDream.utils.Utils;

/**
 * Session Bean implementation class GestorePacchettoPreconfiguratoBean
 */
@Stateless(mappedName = "gestorePacchettoPreconfiguratoBean")
public class GestorePacchettoPreconfiguratoBean implements GestorePacchettoPreconfigurato {

	@PersistenceContext
    private EntityManager em;
	
    /**
     * Default constructor. 
     */
    public GestorePacchettoPreconfiguratoBean() {}

	@Override
	public RisultatoRicercaPPDTO ricercaPP(Date dataFrom, Date dataTo, String dest, Boolean escludiNonInVendita) {
		
		
		
		//1) Controllo se i parametri sono validi
		if(dataFrom == null && dest == null)
			return null;
		
		// Query per campi vuoti
		if (dataFrom == null && dataTo == null && dest.length()==0){
			//2) Genero la query
			TypedQuery<PacchettoPreconfigurato> q_all;
			if (escludiNonInVendita)
				q_all = em.createNamedQuery("pacchettoPreconfigurato.findAllVendibili", PacchettoPreconfigurato.class);
			else
				q_all = em.createNamedQuery("pacchettoPreconfigurato.findAll", PacchettoPreconfigurato.class);
			
			
			//3) Genero il DTO con i dati da restituire al chiamante
			List<PacchettoPreconfigurato> result = q_all.getResultList();
			RisultatoRicercaPPDTO res = new RisultatoRicercaPPDTO();
			
			for(PacchettoPreconfigurato p : result) {
				res.addItem(Utils.convertToDTO(p));
			}
			
			//4) Restituisco il risultato
			return res;
		}
		
		//2) Se non ho inserito un range, setto dateTo=dateFrom, altrimenti eseguo semplicemente la query
		if(dataTo == null)
			dataTo=dataFrom;
		TypedQuery<PacchettoPreconfigurato> q_data;
		TypedQuery<PacchettoPreconfigurato> q_dest;
		if(escludiNonInVendita) {
			q_data = em.createNamedQuery("pacchettoPreconfigurato.findVendibileByData", PacchettoPreconfigurato.class);
			q_dest = em.createNamedQuery("pacchettoPreconfigurato.findVendibileByDest", PacchettoPreconfigurato.class);
		} else {
			q_data = em.createNamedQuery("pacchettoPreconfigurato.findByData", PacchettoPreconfigurato.class);
			q_dest = em.createNamedQuery("pacchettoPreconfigurato.findByDest", PacchettoPreconfigurato.class);
		}
		List<PacchettoPreconfigurato> r_data = null;
		List<PacchettoPreconfigurato> r_dest = null;
		if(dataFrom != null) 
			r_data = q_data.setParameter("dataFrom", dataFrom).setParameter("dataTo", dataTo).getResultList();
		if( dest != null && dest.length() > 0)
			r_dest = q_dest.setParameter("destinazione", dest).getResultList();
		
		List<PacchettoPreconfigurato> result = null;
		
		//Se sono entrambi diversi da null calcolo l'intersezione, 
		//altrimenti tengo come risultato quello non null
		if(dataFrom != null && dest != null && dest.length() > 0) {
			r_data.retainAll(r_dest);
			result = r_data;
		} else {
			result = (dataFrom == null) ? r_dest : r_data;
		}
		
		//3) Genero il DTO con i dati da restituire al chiamante
		RisultatoRicercaPPDTO res = new RisultatoRicercaPPDTO();
		for(PacchettoPreconfigurato p : result) {
			res.addItem(Utils.convertToDTO(p));
		}
		
		//4) Restituisco il risultato
		return res;
	}
	
	@Override
	public void eliminaPP(PacchettoPreconfiguratoDTO pacchettoPreconfiguratoDTO) {
		PacchettoPreconfigurato p = new PacchettoPreconfigurato(em.find(PacchettoPreconfigurato.class, pacchettoPreconfiguratoDTO.getId_pp()));
		p.setEliminato(true);
		p.setIn_vendita(false);
		em.merge(p);
	}

	@Override
	public void creaPP(PacchettoPreconfiguratoDTO pacchettoPreconfiguratoDTO) {
		PacchettoPreconfigurato pp = new PacchettoPreconfigurato();
		List<Volo> voli = new LinkedList<Volo>();
		List<Hotel> hotel = new LinkedList<Hotel>();
		List<IAttivita> attivita = new LinkedList<IAttivita>();
		List<DataPossibilePP> datePossibili = new LinkedList<DataPossibilePP>();
		for (VoloDTO vDTO:pacchettoPreconfiguratoDTO.getVoli()) {
			Volo v = em.find(Volo.class,vDTO.getId());
			voli.add(v);
		}
		for (HotelDTO hDTO:pacchettoPreconfiguratoDTO.getHotel()) {
			Hotel h = em.find(Hotel.class,hDTO.getId());
			hotel.add(h);
		}
		for (EscursioneDTO eDTO:pacchettoPreconfiguratoDTO.getEscursioni()) {
			IAttivita a = em.find(Escursione.class, eDTO.getId());
			attivita.add(a);
		}
		
		for (DataDTO d: pacchettoPreconfiguratoDTO.getDate_possibili()) {
			Date data = d.getData();
			DataPossibilePP dataPossibile = new DataPossibilePP();
			dataPossibile.setData(new java.sql.Date(data.getTime()));
			dataPossibile.setPacchettoPreconfigurato(pp);
			datePossibili.add(dataPossibile);
		}
		pp.setDate_possibili(datePossibili);
		pp.setVoli(voli);
		pp.setAttivita(attivita);
		pp.setHotel(hotel);
		pp.setNome(pacchettoPreconfiguratoDTO.getNome());
		pp.setDestinazione_pacchetto(pacchettoPreconfiguratoDTO.getDestinazione_pacchetto());
		pp.setDurata(pacchettoPreconfiguratoDTO.getDurata());
		pp.setDescrizione(pacchettoPreconfiguratoDTO.getDescrizione());
		pp.setEliminato(pacchettoPreconfiguratoDTO.getEliminato());
		pp.setIn_vendita(pacchettoPreconfiguratoDTO.getInVendita());
		em.persist(pp);
		
	}

	@Override
	public void cambiaStatoInVenditaPP(PacchettoPreconfiguratoDTO pacchettoPreconfiguratoDTO) {
		PacchettoPreconfigurato pp = em.find(PacchettoPreconfigurato.class, pacchettoPreconfiguratoDTO.getId_pp());
		PacchettoPreconfigurato ppModificato = new PacchettoPreconfigurato(pp);
		ppModificato.setIn_vendita(pacchettoPreconfiguratoDTO.getInVendita());
		em.merge(ppModificato);
		
	}
}
